#!/usr/bin/env escript
%% -*- erlang -*-
%%! -sname mswitch_control
%%
%% @author Jean-Lou Dupont
%%

%% Customize here
name() -> "mswitch".
%% ^^^^^^^^^^^^^^^^^

cmds() -> "[status|stop|busses|nodes]".

code_ok()               -> 0.
code_error()            -> 1.
code_daemon_found()     -> 2.
code_daemon_not_found() -> 3.
code_lib_not_found()    -> 4.
code_node_not_found()   -> 5.


err_lib()      -> name()++" library not found".
err_daemon()   -> "daemon not found".
err_node()     -> name()++" node not found".
err_response() -> "invalid response.".


msg_pid()    -> "daemon found, pid: ".
msg_usage()  -> "usage: "++name()++"_control [-q] "++cmds().
msg_kill()   -> "stop command sent".
msg_busses() -> "busses: ".
msg_nodes()  -> "nodes: ".

main(["-q", "stop"])   -> 	run(quiet,   stop);
main(["-q", "status"]) ->	run(quiet, 	 status);
main(["-q", "busses"]) ->	run(quiet, 	 busses);
main(["-q", "nodes"])  ->	run(quiet, 	 nodes);
main(["stop"]) ->			run(verbose, stop);
main(["status"]) ->			run(verbose, status);
main(["busses"]) ->			run(verbose, busses);
main(["nodes"])  ->			run(verbose, nodes);
	
main([]) ->
	msg(verbose, code_ok(), msg_usage()),
	halt(code_ok());
	
main([_Cmd]) ->
	msg(verbose, code_ok(), msg_usage()),
	halt(code_error()).


run(Feedback, stop) ->
	Response = makerpc(pid, status),
	Pid = handle(Feedback, Response, pid),
	os:cmd("kill -9 "++Pid),
	msg(Feedback, code_ok(), msg_kill());
	
	
run(Feedback, busses) ->
	Response = makerpc(busses, getbusses),
	Busses   = handle(Feedback, Response, busses),
	msg(Feedback, code_ok(), msg_busses(), Busses);
	
run(Feedback, nodes) ->
	Response = makerpc(nodes, getnodes),
	Nodes    = handle(Feedback, Response, nodes),
	msg(Feedback, code_ok(), msg_nodes(), Nodes);
	
	
run(Feedback, status) ->
	Response = makerpc(pid, status),
	Pid = handle(Feedback, Response, pid),
	msg(Feedback, code_daemon_found(), msg_pid(), Pid).

	

handle(Feedback, Code, Context) ->
	%%for development
	add_cwd(),
	
	case Code of
		daemon_not_found ->
			msg(Feedback, code_daemon_not_found(), err_daemon());
					
		{error, lib_not_found} ->
			msg(Feedback, code_lib_not_found(), err_lib());
			
		{error, node_not_found} ->
			msg(Feedback, code_node_not_found(), err_node());
	
		{Context, Message} ->
			Message;
			
		Other ->
			io:format("Other: ~p~n", [Other]),
			msg(Feedback, code_error(), err_response())
	end.



add_cwd() ->
	{ok,Cwd}=file:get_cwd(),
	Cp=Cwd++"/ebin",
	code:add_pathsa([Cp]).


msg(Feedback, Code, Msg) ->
	case Feedback of 
		verbose ->
			io:format(name()++"_control: ~s~n", [Msg]);
		_ ->
			ok
	end,	
	halt(Code).

msg(Feedback, Code, Msg1, Msg2) when is_list(Msg2)->
	case Feedback of 
		verbose ->
			io:format(name()++"_control: ~s~p~n", [Msg1, Msg2]);
		_ ->
			ok
	end,	
	halt(Code);
	
	
	
msg(Feedback, Code, Msg1, Msg2) ->
	msg(Feedback, Code, Msg1++Msg2).




%%%%%%%%%%%%%%	
%% RPC related
%%%%%%%%%%%%%%

makerpc(Context, Command) ->
	try
		Reply=rpc(Command),
		case Reply of
			rpcerror ->
				daemon_not_found;
				
			{Context, Message} ->
				{Context, Message}	
		end
	catch
		error:undef ->
			{error, lib_not_found};
		
		_X:_Y ->
			{error, node_not_found}
	end.

	
rpc(Command) ->
	case dorpc(Command) of
		rpcerror ->
			daemon_not_found;
	
		Response ->
			Response
	end.
	


dorpc(Message) ->
	Atom=erlang:list_to_atom(name()),
	Node=make_node(Atom),
	
	case rpc:call(Node, Atom, daemon_api, [Message], 2000) of
		{badrpc, _Reason} ->
			rpcerror;
		
		Other ->
			Other
	end.

extract_host(Node) when is_atom(Node) -> 
	extract_host(atom_to_list(Node));

extract_host(Node) when is_list(Node) ->
	Tokens = string:tokens(Node, "@"),
	lists:last(Tokens).
	


make_node(Name) ->
	make_node(Name, node()).

make_node(Name, Node) when is_atom(Name) ->
	make_node(erlang:atom_to_list(Name), Node);

make_node(Name , Node) when is_list(Name) ->
	Host=extract_host(Node),
	PartialName=string:concat(Name, "@"),
	CompleteName=string:concat(PartialName, Host),
	erlang:list_to_atom(CompleteName).
